package server.main;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.StringTokenizer;

import server.cmd.TbAcntCmd;
import server.cmd.TbCardCmd;
import server.cmd.TbProcessCmd;
import server.cmd.TbProjectCmd;
import server.cmd.TbUserCmd;
import server.dao.TbAcntDAO;
import server.dao.TbProjectDAO;
import server.vo.TbAcntVO;
import server.vo.TbProjectVO;

				
public class ThreadServer {				
	public static void main(String[] args) 
	{			
		String sz_driverClassName, sz_url, sz_username, sz_password;
		int port;
		Connection conn_main;
		
			try 
			{		
			 	 sz_driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
		 	// 	 sz_url = "jdbc:sqlserver://150.28.69.236:1433;databaseName=mexpense";
//			 	 sz_url = "jdbc:sqlserver://10.250.115.81:1433;databaseName=mexpense";
			 	 sz_url = "jdbc:sqlserver://10.250.112.82:1433;databaseName=mexpense";
			     //sz_url = "jdbc:sqlserver://127.0.0.1:1433;databaseName=mexpense";
		 		 sz_username = "sa";
		 		 sz_password = "2088";
		 		 port = 10001;		 		 

		 		 Class.forName(sz_driverClassName);
				 conn_main = DriverManager.getConnection(sz_url, sz_username, sz_password);
		 		 		 		 
		 		 ServerSocket server = new ServerSocket(port);	
		 		 System.out.println("listen : " + port);	
		 		 		 		 
		 		 while(true)
		 		 {	
		 			 Socket sock = server.accept();
		 			 NewThread Newthread = new NewThread(sock, conn_main);
		 			 Newthread.start();
		 		 }	
			}
			catch(Exception e){		
				System.out.println(e);	
			}	
	}		
}			
			
class NewThread extends Thread{			
	private Socket sock;
	
	
	
	Connection conn_thread;
	TbAcntDAO tbAcntDAO;
	TbProjectDAO tbProjectDAO;
	TbAcntVO tbAcntVO;
	TbProjectVO tbProjectVO;
	TbAcntCmd tbAcntCmd;
	TbUserCmd tbUserCmd;
	TbProcessCmd tbProcessCmd;
	TbProjectCmd tbProjectCmd;
	TbCardCmd tbCardCmd;
	
	String szMsg;
	
	public NewThread(Socket sock, Connection conn_param)
	{		
		this.sock = sock;	
			
		conn_thread = conn_param;
		
	} // 占쏙옙占쏙옙		
	public void run(){		
		try{	
			
			tbAcntDAO = new TbAcntDAO();
		 	tbAcntVO = new TbAcntVO();
		 	tbAcntCmd = new TbAcntCmd();
		 	tbUserCmd = new TbUserCmd();
		 	tbProcessCmd = new TbProcessCmd();
		 	tbProjectCmd = new TbProjectCmd();
		 	tbCardCmd = new TbCardCmd();
	
			InetAddress inetaddr = sock.getInetAddress();
			System.out.println(inetaddr.getHostAddress() + " connected ");
			OutputStream out = sock.getOutputStream();
			InputStream in = sock.getInputStream();
			PrintWriter pw = new PrintWriter(new OutputStreamWriter(out, "ms949"));
			BufferedReader br = new BufferedReader(new InputStreamReader(in, "ms949"));	
			String line = null;	
			while((line = br.readLine()) != null){
				
				System.out.println("from CLIENT : " + line);
				
				String[] request = line.split("\\|"); //요청은 구분자 |로 요청CMD와 파라미터로 구분된다는 가정
				String requestCmd = request[0];
				
				
				szMsg="";
				
				StringTokenizer st = new StringTokenizer(line, "^");
				/*
				while (st.hasMoreTokens()) 
				{
				         System.out.println(st.nextToken());
				}
				*/
				
				//FIXME 쓰레드 기반 프로그래밍이므로 동시성 처리에 대한 고려가 필요 ex)Syncronized 메소드 등
				
				try {
					//TODO 이곳에 키워드 추가
					//---------------------------------------------------------------------------------------------------------------
					if("acnt_list".equals(requestCmd)){
						szMsg = tbAcntCmd.acntlist(conn_thread);						
						
					}else if("user_list_all".equals(requestCmd)){ //사용자 전체 리스트 요청
						szMsg = tbUserCmd.getUserListAll(conn_thread);
						
					}else if("user_list_by_name".equals(requestCmd)){ //사용자 리스트 요청 like 검색
						szMsg = tbUserCmd.getUserListByUserName(conn_thread, request[1]);
						
					}else if("user_list_by_id".equals(requestCmd)){ //사용자 리스트 요청 - primary key 
						szMsg = tbUserCmd.getUserListByUserId(conn_thread, request[1]);
						
					}else if("inqr_balance_list".equals(requestCmd)){ //정산내역 목록조회 - defalut (사번, 조회시작일, 조회종료일, 프로젝트코드, 계정코드)
						szMsg = tbProcessCmd.inqrBalanceList(conn_thread, request[1], request[2], request[3], request[4], request[5]);
						
					}else if("inqr_balance_list_by_date".equals(requestCmd)){ //정산내역 목록조회 - 기간별
						szMsg = tbProcessCmd.inqrBalanceListByDate(conn_thread, request[1], request[2], request[3]);
//						
//					}else if("inqr_balance_list_by_pjt".equals(requestCmd)){ //정산내역 목록조회 - 프로젝트별 
//						szMsg = tbProcessCmd.inqrBalanceListByPjt(conn_thread, request[1]);
//						
//					}else if("inqr_balance_list_by_acnt".equals(requestCmd)){ //정산내역 목록조회 - 사용계정별 
//						szMsg = tbProcessCmd.inqrBalanceListByAcnt(conn_thread, request[1], request[2]);
//						
					}else if("delete_balance_list".equals(requestCmd)){ //정산내역삭제
						szMsg = tbProcessCmd.deleteBalanceList(conn_thread, request[1]);
						
					}else if("update_balance_list".equals(requestCmd)){ //정산내역수정
						szMsg = tbProcessCmd.updateBalanceList(conn_thread, request[1], request[2], request[3], request[4]);
						
					}else if("insert_balance_list".equals(requestCmd)){ //정산내역등록 (정산일자, pjt코드, 계정코드, 결재금액, 결재번호))
						szMsg = tbProcessCmd.insertBalanceList(conn_thread, request[1], request[2], request[3], request[4], request[5]);
						
					}else if("pjt_list".equals(requestCmd)){ //프로젝트 전체 리스트 요청
						szMsg = tbProjectCmd.getPjtListAll(conn_thread);
						
					}else if("pjt_list_by_user".equals(requestCmd)){ //프로젝트 목록조회 - 사용자 ID 별 
						szMsg = tbProjectCmd.getPjtListByUserId(conn_thread, request[1]);
						
					}else if("pjt_view_by_code".equals(requestCmd)){ //프로젝트별 조회 - 프로젝트 코드별 
						szMsg = tbProjectCmd.getPjtViewByPjtCode(conn_thread, request[1]);
						
					}else if("acnt_list_by_code".equals(requestCmd)){ //프로젝트별 비용 계정 목록조회 - 프로젝트 코드별 
						szMsg = tbProjectCmd.getAcntListByPjtCode(conn_thread, request[1]);
						
					}else if("user_pjt_regist".equals(requestCmd)) { //프로젝트에 사용자 등록 - 자신이 직접 프로젝트를 선택해서 등록함
						szMsg = tbUserCmd.registUserToPjt(conn_thread, request[1], request[2], request[3]);
						
					}else if("user_list_by_pjt".equals(requestCmd)) { //프로젝트 팀원 조회 - PM일 경우만 가능						
						szMsg = tbUserCmd.getUserListByPjtCode(conn_thread, request[1]);
						
					}else if("inqr_card_bill_list".equals(requestCmd)) { //결제 내역 조회						
						szMsg = tbCardCmd.inqrCardBillList(conn_thread, request[1], request[2], request[3], request[4]);
						
					}else if("insert_card_bill".equals(requestCmd)) { //결제 내역 등록						
						szMsg = tbCardCmd.insertCardBill(conn_thread, request[1], request[2], request[3], request[4], request[5], request[6], request[7], request[8]);
						
					}else if("update_card_bill".equals(requestCmd)) { //결제 내역 변경						
						szMsg = tbCardCmd.updateCardBill(conn_thread, request[1], request[2], request[3]);
						
					}
					
					
					
					
					else {
						//해당 키워드는 지원하지 않음
						throw new UnsupportedOperationException("해당 키워드는 지원하지 않습니다. CMD : "  + requestCmd);
					}
					//---------------------------------------------------------------------------------------------------------------
					
					//TODO 클라이언트에 전달 데이터 방식에 대한 고려가 필요
					//TODO 현재 방식은 String 방식이므로, 다수 row의 데이터에 대한 전달일 경우 row 구분은  ^ field 구분은 | 로 처리   - 클라이언트에 별도 파싱 함수 제공해야함 
					
					if (szMsg != null && szMsg != ""){
						pw.println(szMsg);
						pw.flush();
					} else {
						pw.println("No Data Found");
						pw.flush();
					}
					
					
				} catch (Exception e){ //예외 발생시
					e.printStackTrace();
					pw.println("FAIL" + "|" + e.getMessage());
					pw.flush();
					
					continue;
				}
			}	
			pw.close();	
			br.close();	
			sock.close();	
		}catch(Exception ex){		
			System.out.println(ex);	
		}		
	} // run			
}				
